﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TechnicalAnalysisEngine;
using TechnicalAnalysisEngine.Tests;

namespace TechnicalLibrary.Tests {

    [TestClass]
    public class TestAccumDistLine {
        List<double> _inputHighs;
        List<double> _inputLows;
        List<double> _inputCloses;
        private List<long> _inputVolumes;
        List<double> _expectedValues;

        int _expectedOffset;
        int _expectedResultCount;

        [TestInitialize]
        public void Initialize() {
            _inputHighs = new List<double>()
            {
                62.34,62.05,62.27,60.79,59.93,61.75,60.00,59.00,59.07,59.22,58.75,
                58.65,58.47,58.25,58.35,59.86,59.53,62.10,62.16,62.67,62.38,63.73,
                63.85,66.15,65.34,66.48,65.23,63.40,63.18,62.70
            };

            _inputLows = new List<double>()
            {
                61.37,60.69,60.10,58.61,58.71,59.86,57.97,58.02,57.48,58.30,57.83,
                57.86,57.91,57.83,57.53,58.58,58.30,58.53,59.80,60.93,60.15,62.26,
                63.00,63.58,64.07,65.20,63.21,61.88,61.11,61.25
            };

            _inputCloses = new List<double>()
            {
                62.15,60.81,60.45,59.18,59.24,60.20,58.48,58.24,58.69,58.65,58.47,
                58.02,58.17,58.07,58.13,58.94,59.10,61.92,61.37,61.68,62.09,62.89,
                63.53,64.01,64.77,65.22,63.28,62.40,61.55,62.69
            };

            _inputVolumes = new List<long>()
            {
                7849000,11692000,10575000,13059000,20734000,29630000,17705000,7259000,
                10475000,5204000,3423000,3962000,4096000,3766000,4239000,8040000,6957000,
                18172000,22226000,14614000,12320000,15008000,8880000,22694000,10192000,
                10074000,9412000,10392000,8927000,7460000
            };

            _expectedValues = new List<double>()
            {
               4774.0,-4855.0,-12019.0,-18249.0,-21006.0,-39976.0,-48785.0,-52785.0,-47317.0,
               -48561.0,-47216.0,-49574.0,-49866.0,-49354.0,-47389.0,-50907.0,-48813.0,-32474.0,
               -25128.0,-27144.0,-18028.0,-20193.0,-18000.0,-33099.0,-32056.0,-41816.0,-50575.0,
               -53856.0,-58988.0,-51631.0
            };

            _expectedResultCount = 30;
            _expectedOffset = 0;
        }

        [TestMethod]
        public void TestAccumDistLineValues() {
            var result = AnalysisEngine.AccumDistLine(_inputHighs, _inputLows, _inputCloses, _inputVolumes);

            Assert.AreEqual(_expectedOffset, result.StartIndexOffset, "Offsets do not match");
            Assert.AreEqual(_expectedResultCount, result.Values.Count);

            string message = null;
            bool testResult = true;

            for (int i = 0; i < result.Values.Count; i++) {
                if (!TestHelpers.EqualsWithTolerance(result.Values[i], _expectedValues[i], 1)) // 1% tolerance from expected results
                {
                    message = string.Format("Values do not match at position {0}, expected: {1}, actual: {2} ",
                        i, _expectedValues[i], result.Values[i]);

                    testResult = false;
                    break;
                }
            }

            Assert.IsTrue(testResult, message);
        }

        [TestMethod]
        public void TestAccumDistLinePerformance() {
            Random random = new Random();
            var randomlyGeneratedHighs = new List<double>();
            var randomlyGeneratedLows = new List<double>();
            var randomlyGeneratedCloses = new List<double>();
            var randomlyGeneratedVolumes = new List<long>();

            for (int i = 0; i < 10000; i++) {
                randomlyGeneratedHighs.Add(random.Next(85, 90));
                randomlyGeneratedLows.Add(random.Next(80, 85));
                randomlyGeneratedCloses.Add(random.Next(83, 87));
                randomlyGeneratedVolumes.Add(random.Next(1000000, 1500000));
            }

            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            AnalysisEngine.AccumDistLine(randomlyGeneratedHighs, randomlyGeneratedLows, randomlyGeneratedCloses, randomlyGeneratedVolumes);

            stopWatch.Stop();
            Console.WriteLine(string.Format("AccumDistLine, {0} values, {1} μs", randomlyGeneratedHighs.Count, stopWatch.ElapsedTicks / 10));
        }
    }
}
